package com.black.play.entity;

import com.black.play.component.MineWindow;
import com.black.play.config.AppConfig;
import com.black.play.listener.MineKeyListener;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 继承JPanel 用于定位所有节点对象
 *
 * @author ylx
 */
public class Grid extends JPanel
{
    private static final List<List<Cell>> GRIDS = new ArrayList<>();
    private static final List<Cell> ALL_CELLS = new ArrayList<>();
    protected int num = AppConfig.getInt("mine.num");
    public static final int WIDTH = AppConfig.getInt("window.width");
    public static final int HEIGHT = AppConfig.getInt("window.height");
    public static final int COLS = AppConfig.getOrDefault("grid.cell.cols", 24);
    public static final int ROWS = AppConfig.getOrDefault("grid.cell.rows", 16);
    // 匿名内部类加载配置
    public static final Dimension NODE_SIZE = new Dimension(20, 20)
    {
        {
            if (COLS != 0 && ROWS != 0)
            {
                this.width = WIDTH / COLS;
                this.height = HEIGHT / ROWS;
            }
        }
    };

    static
    {
        initGrid();
        linkGrid();
    }

    /**
     * 根据配置的宽高和行列数初始化网格
     * 生成全列表和二维网格列表
     */
    public static void initGrid()
    {
        for (int rowNum = 0; rowNum < ROWS; rowNum++)
        {
            List<Cell> row = new ArrayList<>();
            for (int colNum = 0; colNum < COLS; colNum++)
            {
                Cell cell = new Cell(colNum * NODE_SIZE.width, rowNum * NODE_SIZE.height);
                row.add(cell);
                ALL_CELLS.add(cell);
            }
            GRIDS.add(row);
        }
    }

    /**
     * 将网格上下左右进行链接 互相持有引用
     */
    public static void linkGrid()
    {
        for (int y = 0; y < ROWS; y++)
        {
            List<Cell> row = GRIDS.get(y);
            for (int x = 0; x < COLS; x++)
            {
                Cell cell = row.get(x);
                // x比0大的时候有左节点
                if (x > 0)
                {
                    cell.left = row.get(x - 1);
                }
                // y比0大的时候有上节点
                if (y > 0)
                {
                    cell.up = GRIDS.get(y - 1).get(x);
                }
                // x比最大值小的时候有右节点
                if (x < COLS - 1)
                {
                    cell.right = row.get(x + 1);
                }
                // y比最大值小的时候有下节点
                if (y < ROWS - 1)
                {
                    cell.down = GRIDS.get(y + 1).get(x);
                }
            }
        }
    }

    /**
     * 实例化时构造必要参数
     */
    public Grid()
    {
        // 标准网格布局
        this.setLayout(new GridLayout(ROWS, COLS));
        // 设置画板大小铺满窗口
        this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        this.setBackground(MineWindow.BACKGROUND);
        GRIDS.forEach(row -> row.forEach(this::add));
        // 允许键盘事件聚焦
        addKeyListener(MineKeyListener.getInstance());
        setFocusable(true);
        requestFocusInWindow();
    }

    /**
     * 开始游戏时的初始化内容
     */
    public void init()
    {
        initMines();
        initNumbers();
    }

    /**
     * 初始化雷区
     */
    private void initMines()
    {
        // 列表打乱
        Collections.shuffle(ALL_CELLS);
        int size = ALL_CELLS.size();
        for (int i = 0; i < size; i++)
        {
            // 初始化每个cell
            Cell cell = ALL_CELLS.get(i);
            cell.init();
            // 将前num个指定为雷区
            if (i < num)
            {
                cell.setMine(true);
                cell.setValue(CellValue.MINE);
            }
        }
    }

    /**
     * 雷区初始化后 初始化数字
     */
    private void initNumbers()
    {
        for (Cell cell : ALL_CELLS)
        {
            // 如果当前节点是雷 则跳过
            if (cell.isMine())
            {
                continue;
            }
            // 获取邻居中雷区的个数
            List<Cell> neighbors = cell.getNeighbors();
            int count = (int) neighbors.stream().filter(Cell::isMine).count();
            cell.setValue(CellValue.values()[count]);
        }
    }

    /**
     * 判断通关
     *
     * @return 是否通关
     */
    public boolean isSuccess()
    {
        // 统计雷区正确标记的个数
        long flagCount = getRightFlagCount();
        if (flagCount == num)
        {
            return true;
        }
        // 统计所有节点打开的个数
        long openCount = ALL_CELLS.stream().filter(cell -> cell.getStatus() == CellStatus.OPEN).count();
        return openCount == ALL_CELLS.size() - num;
    }

    public int getRightFlagCount()
    {
        return (int) ALL_CELLS.stream().filter(cell -> cell.getTempValue() == CellValue.FLAG && cell.isMine()).count();
    }

    /**
     * 死亡结束
     * 展示所有雷
     * 计时器停止
     * 清空监听
     */
    public void fail()
    {
        ALL_CELLS.forEach(cell ->
        {
            if (cell.isMine())
            {
                cell.setStatus(CellStatus.OPEN);
                cell.updateUI();
            }
            cell.stopListener();
        });
    }

    /**
     * 通关
     * 展示所有数字
     * 标记所有雷区
     */
    public void success()
    {
        ALL_CELLS.forEach(cell ->
        {
            if (!cell.isMine())
            {
                cell.setStatus(CellStatus.OPEN);
            }
            else
            {
                cell.setTempValue(CellValue.FLAG);
                cell.setStatus(CellStatus.HALF_OPEN);
            }
            cell.updateUI();
            cell.stopListener();
        });
    }
}
